package com.liveMobile.Screen;

import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.bridge.WritableMap;
import com.liveMobile.Screen.recorder.ScreenRecorder;
import com.liveMobile.Screen.recorder.ScreenType;
import com.pedro.common.ConnectChecker;

import java.util.HashMap;
import java.util.Objects;

public class ScreenModules extends ReactContextBaseJavaModule implements ActivityEventListener, ConnectChecker {
    private static final int CODE_REQUEST_RECORD = 101;
    private final ReactApplicationContext mContext;
    private boolean isAllowRecord = true;
    private boolean isBound = false;
    private ScreenRecorder screenRecorderService;

    private final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 获取ScreenRecorder实例
            Log.i("onServiceConnected","onServiceConnected");
            ScreenRecorder.LocalBinder binder = (ScreenRecorder.LocalBinder) service;
            screenRecorderService = binder.getService();
            isBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBound = false;
        }
    };
    private MediaProjectionManager mMediaProjectionManager;
    private String url;

    public ScreenModules(ReactApplicationContext reactContext) {
        super(reactContext);
        mContext = reactContext;
        this.mContext.addActivityEventListener(this);
    }

    @NonNull
    @Override
    public String getName() {
        //注意 这里的名字才是RN中被调用的名字
        return "ScreenClient";
    }

    public Context getContext() {
        return mContext.getApplicationContext();
    }

    public Activity getActivity() {
        return mContext.getCurrentActivity();
    }

    @ReactMethod
    public void init(ReadableMap msg, Callback callback) {
        try {

            Log.i("init", "init");
//            screen.callback = callback;
            ReadableNativeMap map = (ReadableNativeMap) msg;
            HashMap<String, Object> map2 = map.toHashMap();
            this.url = (String) map2.get("url");
            Log.i("init", "init2");
            if (!this.isAllowRecord) {
                this.getResult(ScreenType.PROHIBIT_SCREEN_RECORDING.getCode(), ScreenType.PROHIBIT_SCREEN_RECORDING.getName(), callback);
                Log.i("init", "init3");
            } else if (screenRecorderService != null && screenRecorderService.isRecording()) {
                Log.i("init", "init4");
                this.getResult(ScreenType.SCREEN_RECORDING_IN_PROGRESS.getCode(), ScreenType.SCREEN_RECORDING_IN_PROGRESS.getName(), callback);
            } else {
                if (this.checkRecordPermission()) {
                    this.requestPermissions();
                }

            }

        } catch (RuntimeException e) {
            this.getResult(500, e.toString(), callback);
        }

    }

    @ReactMethod
    public void start() {
        screenRecorderService.startStream(this.url);
    }

    private WritableMap getResult(int code, String msg) {
        WritableMap result = Arguments.createMap();
        result.putInt("code", code);
        result.putString("msg", msg);
        return result;
    }

    void getResult(int code, String msg, Callback callback) {
        WritableMap result = Arguments.createMap();
        result.putInt("code", code);
        result.putString("msg", msg);
        callback.invoke(result);
        Log.d("getResult", "code" + code + ",msg" + msg);
    }


    boolean checkRecordPermission() {
        Log.i("checkRecordPermission", "checkRecordPermission");
        Activity activity = this.getActivity();
        int a = ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO);
        int c = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        int d = ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
        int checkPermission = a + c + d;
        Log.i("checkRecordPermission", "checkRecordPermission:" + a + "," + c + "," + d);
        if (checkPermission != 0) {
            ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
            return false;
        }
        return true;
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 2) {
            if (grantResults[0] == 0) {
                this.requestPermissions();
            } else {
                throw new RuntimeException(ScreenType.REFUSE_SCREEN_RECORDING.getName());
            }
        }

    }

    public void requestPermissions() {

        try {
            Log.i("requestPermissions", "requestPermissions");
            if (this.mMediaProjectionManager == null) {
                this.mMediaProjectionManager = (MediaProjectionManager) this.getActivity().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
            }

            Intent captureIntent = this.mMediaProjectionManager.createScreenCaptureIntent();
            this.getActivity().startActivityForResult(captureIntent, CODE_REQUEST_RECORD);
            Log.i("requestPermissions public", "requestPermissions public");
        } catch (RuntimeException e) {
            Log.i("requestPermissions err", e.toString());
        }

    }

    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, @Nullable Intent data) {

        Log.i("onActivityResult", "onActivityResult");
        if (requestCode == CODE_REQUEST_RECORD && resultCode == Activity.RESULT_OK) {

            Intent recordService = new Intent(this.getActivity(), ScreenRecorder.class);
            recordService.putExtra("url", url);
            recordService.putExtra("resultCode", resultCode);
            recordService.putExtra("data", data);
            this.getActivity().startService(recordService);

            final boolean b = this.getActivity().bindService(recordService, serviceConnection, Context.BIND_AUTO_CREATE);
            if (b) {
                Log.e("bindService", "绑定成功 ");
            } else {
                Log.e("bindService", "绑定失败");
            }
        } else {
            throw new RuntimeException("录屏回掉失败");
        }
    }

    @Override
    public void onNewIntent(Intent intent) {

    }

    public void destroy() {
        Intent service = new Intent(this.getActivity(), ScreenRecorder.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            this.getActivity().startForegroundService(service);
        } else {
            this.getActivity().stopService(service);
        }
        this.onStop();
    }

    protected void onStop() {
        if (isBound) {
            // 解绑服务
            this.getActivity().unbindService(serviceConnection);
            isBound = false;
        }
    }


    //  允许录屏
    @ReactMethod
    public void noRecord() {
        this.isAllowRecord = false;
        Objects.requireNonNull(mContext.getCurrentActivity()).getWindow().addFlags(8192);
    }

    //  禁止录屏
    @ReactMethod
    public void allowRecord() {
        this.isAllowRecord = true;
        Objects.requireNonNull(mContext.getCurrentActivity()).getWindow().clearFlags(8192);
    }

    @Override
    public void onAuthError() {

    }

    @Override
    public void onConnectionStarted(@NonNull String s) {
        Log.i("onConnectionStarted", s);
    }

    @Override
    public void onConnectionSuccess() {

    }

    @Override
    public void onConnectionFailed(@NonNull String s) {
        Log.i("onConnectionFailed", s);
    }

    @Override
    public void onNewBitrate(long l) {
//        Log.i("onNewBitrate",);
    }

    @Override
    public void onDisconnect() {

    }

    @Override
    public void onAuthSuccess() {

    }
}
